package com.wys.ws_im.websocket;

import com.alibaba.fastjson.JSON;
import com.wys.ws_im.dao.AccountDao;
import com.wys.ws_im.entity.Message;
import com.wys.ws_im.entity.OnlineUser;
import com.wys.ws_im.service.MessageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * WebSocket 聊天服务端
 *
 * @see ServerEndpoint WebSocket服务端 需指定端点的访问路径
 * @see Session   WebSocket会话对象 通过它给客户端发送消息
 */
@Slf4j
@Component
@ServerEndpoint("/chat/{sendId}/{ulid}")
public class WebSocketChatServer {

    @Autowired
    private AccountDao accountDao;

//    @Autowired
    public static MessageService messageService;

    // aid 对应 OnlineUser  online窗口
    public static Map<Integer, OnlineUser> onlineUserMap = new ConcurrentHashMap<>();

    // aid 对应 Session
    private Map<Integer, String> stringSessionMap = new ConcurrentHashMap<>();

    private static Map<String, Session> onlineSessions = new ConcurrentHashMap<>();

    @Autowired
    public WebSocketChatServer(MessageService messageService) {
        WebSocketChatServer.messageService = messageService;
    }

    public WebSocketChatServer() {

    }

    /**
     * 打开聊天界面
     * 返回界面的初始消息
     * @param session
     * @param sendId
     * @param ulid
     */
    @OnOpen
    public String onOpen(Session session,
                       @PathParam("sendId") Integer sendId,
                       @PathParam("ulid") Integer ulid
                       ) {


        initChat(session, sendId, ulid);
        return "xczc";

    }

    /**
     * 发送消息
     * @param session
     * @param jsonStr   包含有发送方id，发送消息内容，接收方id
     */
    @OnMessage
    public void onMessage(Session session, String jsonStr) {

        log.info("jsonStr {}" + jsonStr);

        // 单聊
        setOne(jsonStr);

    }


    /**
     * 退出
     * @param session
     */
    @OnClose
    public void onClose(Session session) {

        // 关闭会话  移除在线
        for(Map.Entry<Integer, OnlineUser> entry: onlineUserMap.entrySet()) {
           if (entry.getValue().getSession().equals(session)) {
               onlineUserMap.remove(entry.getKey());
           }
        }

        log.info("session: {} chat onClose", session);
        try {
            session.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }


    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }



    private static void sendMessageToAll(String msg) {

    }

    /**
     * 单聊
     * @param jsonStr
     */
    private void setOne(String jsonStr) {

//        for(Map.Entry<Integer, OnlineUser> entry: onlineUserMap.entrySet()) {
//            System.out.println("sendId " + entry.getKey() +
//                    " sessionid " + entry.getValue().getSession().getId());
////            log.info("{}", entry.getValue().getSession());
//            System.out.println(" getBasicRemote "
//                    + entry.getValue().getSession().getBasicRemote());
//        }

//        for(Map.Entry<String, Session> entry: onlineSessions.entrySet()) {
//            System.out.println("onlineSessions sendId: " + entry.getKey() +
//                    " onlineSessions getBasicRemote " + entry.getValue().getBasicRemote());
//        }

        Message message = JSON.parseObject(jsonStr, Message.class);
        message.setSendTime(new Date());
        message.setUpdateTime(new Date());

        log.info("me s {}", message);

        // 获得发送方
        OnlineUser sendUser = onlineUserMap.get(message.getSendId());
        Session sendUserSession = sendUser.getSession();
        // 获得接收方
        OnlineUser receiveUser = onlineUserMap.get(message.getReceiveId());

        String messStr = JSON.toJSONString(message);

        /**
         * 判断接收方是否在线
         */
        // 单聊，不在线
        if (receiveUser == null) {
            // 消息进行存储，并将消息标记为未读，记录到数据库，下次对方上线时推送给对方
            System.out.println(" = 单聊，不在线 消息进行存储，并将消息标记为未读，记录到数据库，下次对方上线时推送给对方");
            // 发送方也要收到消息

            try {
                sendUserSession.getBasicRemote().sendText(messStr);
            } catch (IOException e) {
                e.printStackTrace();
            }
            messageService.saveOfflineMessage(message);


        }
        // 在线
        else {
            // 及时推送
            Session receiveUserSession = receiveUser.getSession();
            try {
                sendUserSession.getBasicRemote().sendText(messStr);
                receiveUserSession.getBasicRemote().sendText(messStr);
            } catch (IOException e) {
                e.printStackTrace();
            }
            messageService.saveMessage(message);

        }

    }

    /**
     * 打开聊天窗口 初始化 数据
     * 获取数据
     * @param session
     */
    public void initChat(Session session, Integer sendId, Integer ulid) {

        // 打开聊天窗口获取消息
        // 初始化消息
        List<Message> messages = messageService.getOnOpenMessage(sendId, ulid);
        // 加入在线用户
        if (!onlineUserMap.containsKey(sendId)) {
            onlineUserMap.put(sendId, new OnlineUser(session));
//            log.info(" {} 连接上了 {}接收id " + sendId + "ulid " + ulid
//                    + "session Id: " + session.getId());
        }
        // 前面打开过了
        // 先移除前面的，关闭前面的
        else {
            OnlineUser removeUser = onlineUserMap.get(sendId);
            try {
                removeUser.getSession().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            onlineUserMap.remove(sendId);
            onlineUserMap.put(sendId, new OnlineUser(session));
        }

        try {
            session.getBasicRemote().sendText(JSON.toJSONString(messages));
        } catch (IOException e) {
            e.printStackTrace();
        }
//        for(Map.Entry<Integer, OnlineUser> entry: onlineUserMap.entrySet()) {
//            System.out.println("init sendId: " + entry.getKey() +
//                    " init session id " + entry.getValue().getSession().getId());
////            log.info("{}", entry.getValue().getSession());
//            System.out.println(" getBasicRemote "
//                    + entry.getValue().getSession().getBasicRemote());
//        }
        log.info("init message");

//        for(Map.Entry<String, Session> entry: onlineSessions.entrySet()) {
//            System.out.println("onlineSessions sendId: " + entry.getKey() +
//                    " onlineSessions getBasicRemote " + entry.getValue().getBasicRemote());
//        }


    }



}